﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LinqToLfsWorld;
using LinqToLfsWorld.Extensions;
using LinqToLfsWorld.Searches;

namespace LibraryTest
{
	/// <summary>
	/// Summary description for UnitTest1
	/// </summary>
	[TestClass]
	public class LfsWorldLibraryTest
	{
		static string _lfswIdentKey = "G1ilghfc62YrQ0dUJ497ajfF2MkobIcp";
		static LfsWorldContext _lfswContext = null;

		public LfsWorldLibraryTest()
		{
		}

		private TestContext testContextInstance;

		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}

		#region Additional test attributes
		//
		// You can use the following additional attributes as you write your tests:
		//
		// Use ClassInitialize to run code before running the first test in the class
		// [ClassInitialize()]
		// public static void MyClassInitialize(TestContext testContext) { }
		//
		// Use ClassCleanup to run code after all tests in a class have run
		// [ClassCleanup()]
		// public static void MyClassCleanup() { }
		//
		// Use TestInitialize to run code before running each test 
		// [TestInitialize()]
		// public void MyTestInitialize() { }
		//
		// Use TestCleanup to run code after each test has run
		// [TestCleanup()]
		// public void MyTestCleanup() { }
		//
		#endregion

		[ClassInitialize]
		public static void ContextInitialize(TestContext context)
		{
			_lfswContext = new LfsWorldContext(_lfswIdentKey);
			_lfswContext.PremiumPubstatAccess = false;
		}

		[ClassCleanup]
		public static void ContextClose()
		{
			if (_lfswContext != null)
				_lfswContext.Dispose();
			_lfswContext = null;
		}

		[TestMethod]
		public void TimestampExtensionTest()
		{
			DateTime time = DateTime.Now;
			int timestamp = time.ToUnixTimestamp();
			DateTime now = DateTimeExtensions.FromUnixTimestamp(timestamp);

			Assert.AreEqual(DateTime.Now.ToString(), now.ToString());
		}

		[TestMethod]
		public void HotlapLogTest()
		{
			int startTime = DateTime.Parse("30/01/2008").ToUnixTimestamp();

			var q = from log in _lfswContext.HotlapLog
					where log.Steering == "ms" && log.LogFilter == (int)HotlapLogFilter.Top10
					&& log.StartTime == startTime && log.Lines == 30
					select log;

			var list = q.ToList();

			Assert.IsNotNull(list);
		}

		[TestMethod]
		public void HostsTestMethod()
		{

			var query = from host in _lfswContext.Hosts
						select host;

			var hosts = query.ToList();

			Assert.IsNotNull(hosts, "The hosts list is null");
			Assert.AreNotEqual<int>(0, hosts.Count, "There were no hosts");

		}

		[TestMethod]
		public void RacerStatSearch()
		{

			var query = from stat in _lfswContext.RacerStats
						where stat.RacerName == "elkdanger"
						select stat;

			var hosts = query.ToList();

		}

		[TestMethod]
		public void HotlapChartTest()
		{

			var q = from hc in _lfswContext.HotlapChart
					where hc.Car == "XRG"
					&& hc.TrackIdent == "000"
					&& hc.SteeringMethod == "ms"
					select hc;

			var list = q.ToList();
		}

		int _cachingTest_RequestIndex = 0;

		[TestMethod]
		public void CachingTest()
		{
			_lfswContext.PremiumPubstatAccess = false;
			_lfswContext.RequestMade += new LfsRequestHandler(CachingTest_RequestMade);
			_lfswContext.CachingEnabled = true;

			Assert.AreEqual(false, _lfswContext.PremiumPubstatAccess);

			// Caching should be enabled by default
			Assert.AreEqual<bool>(true, _lfswContext.CachingAvailable);

			_lfswContext.CacheTime = TimeSpan.FromSeconds(20);

			// Verifies that the cache time can be set properly
			Assert.AreEqual(_lfswContext.CacheTime.Seconds, 20);

			// Verifies that we can make a request
			Assert.AreEqual(true, _lfswContext.CanMakeRequest);

			var q = _lfswContext.Hosts.Select(h => h);

			for (int i = 0; i < 20; i++)
			{
				var list = q.ToList();

				// Demonstrates that populated lists are coming back every time
				Assert.AreNotEqual<int>(0, list.Count);
			}

			_lfswContext.CachingEnabled = false;
			Assert.AreEqual<bool>(false, _lfswContext.CachingAvailable);
		}

		void CachingTest_RequestMade(object sender, LfsWorldResponse response)
		{
			
			if(_cachingTest_RequestIndex == 0)
				Assert.AreEqual<bool>(false, response.FromCache);
			else
				Assert.AreEqual<bool>(true, response.FromCache);

			_cachingTest_RequestIndex++;
		}

		[TestMethod]
		[ExpectedException(typeof(LinqToLfsWorld.PubstatRequestException))]
		public void NoCachingTest()
		{
			_lfswContext.CachingEnabled = false;
			_lfswContext.PremiumPubstatAccess = false;

			Assert.AreEqual<bool>(false, _lfswContext.CachingAvailable);

			// Try and read the hosts in quick succession with caching disabled
			var q = _lfswContext.Hosts.Select(h => h);

			var list1 = q.ToList();
			var list2 = q.ToList();		// should throw an exception - too many requests
		}

		[TestMethod]
		public void PremiumAccessTest()
		{
			// Should be false by default.
			_lfswContext.PremiumPubstatAccess = false;
			Assert.AreEqual(false, _lfswContext.PremiumPubstatAccess);

			_lfswContext.PremiumPubstatAccess = true;
			Assert.AreEqual(true, _lfswContext.PremiumPubstatAccess);
		}

		[TestMethod]
		public void TeamsTest()
		{
			var q = from t in _lfswContext.Teams
					select t;

			var teams = q.ToList();

			Assert.AreNotEqual(0, teams.Count);
		}

		[TestMethod]
		public void ElkdangerHostTest()
		{
			var hosts = (from host in _lfswContext.Hosts select host).ToList();
			var myHost = hosts.Where(h => h.HostName == "elkdanger_test").SingleOrDefault();

			Assert.IsNotNull(myHost);
		}

		[TestMethod]
		public void WorldRecordsTest()
		{
			var q = from wr in _lfswContext.WorldRecords
					where wr.TrackIdent == "000" && wr.Car == "XRG"
					select wr;

			var wrs = q.ToList();
		}

		[TestMethod]
		public void ConfigurationTest()
		{
			Assert.IsNotNull(_lfswContext.Configuration);
		}

		private bool _requestMadeTest = false;

		[TestMethod]
		public void RequestMadeTest()
		{
			_lfswContext.RequestMade += new LfsRequestHandler(Context_RequestMade);

			var q = from stats in _lfswContext.RacerStats
					where stats.RacerName == "elkdanger"
					select stats;

			var list = q.ToList();

			Assert.AreEqual(true, _requestMadeTest);
		}

		void Context_RequestMade(object sender, LfsWorldResponse response)
		{
			Assert.IsNotNull(sender);
			Assert.IsNotNull(response);
			_requestMadeTest = true;
		}

		[TestMethod]
		public void Search2Test()
		{
			RacerFuelSearch search = new RacerFuelSearch(_lfswContext);

			var query = from f in search 
						where f.RacerName == "elkdanger"
						select f;

			var list = query.ToList();
		}

	}
}
